﻿using GrapeCity.Forguncy.Commands;
using Qdrant.Client.Grpc;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

namespace QdrantConnector
{
    public class Converters
    {

        public static IReadOnlyList<PointStruct> ToPoint(string listJSON)
        {
            var data = JsonSerializer.Deserialize<List<QVector>>(listJSON);

            if (data == null)
                throw new InvalidOperationException("加载矢量集合出错，传入参数不是 List<QVector> 类型。");

            var data2 = new List<PointStruct>();

            foreach (var qv in data)
            {
                var item = new PointStruct
                {
                    Id = new PointId { Num = (ulong)qv.id },
                    Vectors = new Vectors { Vector = new Vector { Data = { qv.embedding } } },

                };

                if (qv.payload != null)
                {
                    foreach (var kvp in qv.payload)
                    {
                        var ele = (JsonElement)kvp.Value;

                        if(ele.ValueKind == JsonValueKind.Null)
                        {
                            item.Payload.Add(kvp.Key, new Value { NullValue = NullValue.NullValue });
                        }
                        else if (ele.ValueKind == JsonValueKind.String)
                        {
                            item.Payload.Add(kvp.Key, new Value { StringValue = ele.GetString() });
                        }
                        else if (ele.ValueKind == JsonValueKind.Number)
                        {
                            if (ele.TryGetInt32(out int intValue))
                            {
                                item.Payload.Add(kvp.Key, new Value { IntegerValue = intValue });
                            }
                            else if (ele.TryGetDouble(out double doubleValue))
                            {
                                item.Payload.Add(kvp.Key, new Value { DoubleValue = doubleValue });
                            }
                        }
                        else if (ele.ValueKind == JsonValueKind.True || ele.ValueKind == JsonValueKind.False)
                        {
                            item.Payload.Add(kvp.Key, new Value { BoolValue = ele.GetBoolean() });
                        }
                        else
                        {
                            // 其他类型暂不处理
                            continue;
                        }
                    }
                }

                data2.Add(item);
            }

            return data2;
        }

        public static ReadOnlyMemory<float> ToVector(string embedding)
        {
            if (string.IsNullOrEmpty(embedding))
                return null;

            embedding = embedding.Trim('[', ']'); // 去除方括号   
            embedding = embedding.Replace(" ", ""); // 去除空格
            embedding = embedding.Replace("\r\n", ""); // 去除换行符

            var arr = embedding.Split(',');
            float[] result = new float[arr.Length];
            for (int i = 0; i < arr.Length; i++)
            {
                result[i] = float.Parse(arr[i]);
            }
            return result;
        }

        public static object ToObject(Value value)
        {

            if (value == null || value.HasNullValue) return null;
            if (value.HasStringValue) return value.StringValue;
            if (value.HasBoolValue) return value.BoolValue;
            if (value.HasDoubleValue) return value.DoubleValue;
            if (value.HasIntegerValue) return value.IntegerValue;


            return null;
        }

        public static WithPayloadSelector ToPayloadSelector(bool shouldInclude)
        {

            WithPayloadSelector selector = new();

            // 添加负载属性到选择器中
            selector.Enable = shouldInclude;

            return selector;
        }

        public class QVector
        {
            public int id { get; set; }
            public float[] embedding { get; set; }
            public Dictionary<string, object> payload { get; set; }
        }
    }
}
